home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Demo Folder / Toh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  5.2 KB  |  243 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Blob Manager Demonstration:  Tower of Hanoi
  3.  *
  4.  * 26 July 1986    Paul DuBois
  5.  */
  6.  
  7. # include    "TransSkel.h"
  8.  
  9. # include    "BlobMgr.h"
  10. # include    "BlobDemo.h"
  11.  
  12.  
  13. # define    xBase        17    /* upper left corner of apparatus base */
  14. # define    yBase        130
  15. # define    baseHeight    12    /* length is computed */
  16. # define    slotHeight    18    /* size of disk slots */
  17. # define    slotWidth    100
  18. # define    slotHGap    20    /* horiz. gap between slots    */
  19. # define    slotVGap    0    /* vert. gap between slots */
  20. # define    hExtra        20    /* extra space at ends of base */
  21. # define    nDisks        6    /* number of disks */
  22. # define    postWidth    12    /* height is computed */
  23.     
  24.  
  25. static WindowPtr        wind;
  26. static BlobSetHandle    donors;
  27. static BlobSetHandle    receptors;
  28. static BlobHandle        tower[3][nDisks];    /* induced data structure */
  29.  
  30.  
  31.  
  32. static void
  33. DrawApparatus (void)
  34. {
  35. short    postHeight, baseWidth, h, v, i;
  36. Rect    r;
  37.  
  38.     postHeight = nDisks * (slotHeight + slotVGap) + postWidth/2;
  39.     h = xBase + hExtra + slotWidth/2 - postWidth/2;
  40.     SetRect (&r, h, yBase - postHeight, h + postWidth, yBase+postWidth/2);
  41.  
  42.     for (i = 0; i < 3; ++i)
  43.     {
  44.         FillRoundRect (&r, postWidth, postWidth, gray);
  45.         FrameRoundRect (&r, postWidth, postWidth);
  46.         OffsetRect (&r, slotWidth + slotHGap, 0);
  47.     }
  48.  
  49.     baseWidth = 3 * slotWidth + 2 * slotHGap + 2 * hExtra;
  50.     SetRect (&r, xBase, yBase, xBase + baseWidth, yBase + baseHeight);
  51.     FillRect (&r, dkGray);
  52.     FrameRect (&r);
  53. }
  54.  
  55.  
  56. /*
  57.  * If a disk was moved onto a pile, but has empty slots under it,
  58.  * drop it until it can't go any farther.
  59.  */
  60.  
  61. static void
  62. DropDisk (void)
  63. {
  64. short    i, j;
  65.  
  66.     for (i = 0; i < 3; ++i)
  67.     {
  68.         for (j = nDisks - 1; j > 0; --j)    /* don't check bottom pos */
  69.         {
  70.             if (BGlob (tower[i][j]) != nil)
  71.             {
  72.                 if (BGlob (tower[i][j-1]) == nil)
  73.                     TransferGlob (tower[i][j], tower[i][j-1]);
  74.             }
  75.         }
  76.     }
  77. }
  78.  
  79.  
  80. static pascal void
  81. Mouse (Point pt, long t, short mods)
  82. {
  83.     BlobClick (pt, t, nil, receptors);
  84.     DropDisk ();
  85. }
  86.  
  87.  
  88. /*
  89.  * The advisory functions as follows:  receptor clicks are checked
  90.  * and if the click isn't in the top disk of a pile, the click is
  91.  * ignored (message advRClick).  When a receptor is dragged somewhere
  92.  * else, it must be to a pile in which the disk under it is larger -
  93.  * can't drag onto a smaller disk (message advXfer).
  94.  */
  95.  
  96. static pascal Boolean
  97. Advisory (short mesg, BlobHandle b)
  98. {
  99. BlobHandle    g;
  100. short        index, pile, piece, i;
  101. static short    srcRank;
  102.  
  103.     index = GetBlobIndex (receptors, b);
  104.     pile = index / nDisks;        /* 0 .. 2 */
  105.     piece = index % nDisks;        /* 0 .. nDisks-1 */
  106.     
  107.     switch (mesg)
  108.     {
  109.         case advRClick:
  110.         {
  111.             if (piece < nDisks - 1 && BGlob (NextBlob (b)) != nil)
  112.                 return (false);
  113.             srcRank = GetBRefCon (BGlob (b));    /* rank of dragged piece */
  114.             break;
  115.         }
  116.         case advXfer:
  117.         {
  118.             for (i = 0; i < piece; ++i)
  119.             {
  120.                 if ((g = BGlob (tower[pile][i])) != nil)
  121.                 {
  122.                     if (GetBRefCon (g) > srcRank)
  123.                         return (false);
  124.                 }
  125.             }
  126.             break;
  127.         }
  128.     }
  129.     return (true);
  130. }
  131.  
  132.  
  133. static pascal void
  134. Update (Boolean resized)
  135. {
  136.     DrawControls (wind);
  137.     DrawApparatus ();
  138.     DrawBlobSet (receptors);
  139. }
  140.  
  141.  
  142. static pascal void
  143. Activate (Boolean active)
  144. {
  145.     if (active)
  146.     {
  147.         SetDragRects (wind);
  148.         SetBCPermissions (false, true, false, false, false);
  149.         SetBCAdvisory (Advisory);
  150.     }
  151.     else
  152.         SetBCAdvisory (nil);
  153. }
  154.  
  155. /*
  156.  * Call this before calling MakeDonors().
  157.  */
  158.  
  159. static void
  160. MakeReceptors (void)
  161. {
  162. BlobHandle    b;
  163. Rect        r, r2, r3;
  164. short        i, j, h, v;
  165.  
  166.     receptors = NewBlobSet ();
  167.     for (i = 0; i < 3; ++i)
  168.     {
  169.         for (j = 0; j < nDisks; ++j)
  170.         {
  171.             b = NewBlob (receptors, true, 0, false, 0L);
  172.             tower[i][j] = b;
  173.             OpenBlob ();
  174.             SetRect (&r, 0, 0, slotWidth, slotHeight);
  175.             h = slotWidth/2 - postWidth/2;
  176.             SetRect (&r2, h, -1, h + postWidth, slotHeight+1);
  177.             FillRect (&r2, gray);    /* fill in post area */
  178.             SetRect (&r3, 0, 0, h, slotHeight);    /* erase on sides of post */
  179.             EraseRect (&r3);
  180.             SetRect (&r3, h + postWidth, 0, slotWidth, slotHeight);
  181.             EraseRect (&r3);
  182.             FrameRect (&r2);
  183.             r2 = r;
  184.             InsetRect (&r2, 0, 1);
  185.             CloseRectBlob (b, &r2, &r);
  186.             h = xBase + hExtra + i * (slotWidth + slotHGap);
  187.             v = yBase - (j+1) * (slotHeight + slotVGap);
  188.             MoveBlob (b, inFullBlob, h, v);
  189.         }
  190.     }
  191. }
  192.  
  193.  
  194. /*
  195.  * Make donors.  These are the pieces that get moved.  They're always
  196.  * attached to some receptor, and just float from one receptor to
  197.  * another.  The rank of each piece is stored in the reference constant
  198.  * field.  The bottom piece is 0, the top is nDisks-1.
  199.  */
  200.  
  201. static void
  202. MakeDonors (void)
  203. {
  204. short        i, j;
  205. BlobHandle    b;
  206. Rect        r, r2;
  207.  
  208.     donors = NewBlobSet ();
  209.     for (i = 0; i < nDisks; ++i)
  210.     {
  211.         b = NewBlob (donors, true, 1, false, (long) i);    /* refCon is disk rank */
  212.         OpenBlob ();
  213.         SetRect (&r, 0, 0, slotWidth, slotHeight);
  214.         j = 20 + (nDisks-i-1) * 4;
  215.         SetRect (&r2, slotWidth/2 - j, 1, slotWidth/2 + j, slotHeight-1);
  216.         EraseRect (&r);
  217.         FrameRoundRect (&r2, slotHeight, slotHeight);
  218.         CloseRectBlob (b, &r, &r);
  219.         GlueGlob (b, tower[0][i]);    /* glue to first column */
  220.     }
  221.  
  222. }
  223.  
  224.  
  225. void
  226. TohInit (void)
  227. {
  228.     SkelWindow (wind = GetDemoWind (tohWindRes),
  229.                 Mouse,            /* mouse clicks */
  230.                 nil,            /* key clicks */
  231.                 Update,            /* updates */
  232.                 Activate,        /* activate/deactivate events */
  233.                 nil,            /* close window */
  234.                 DoWClobber,        /* dispose of window */
  235.                 nil,            /* idle proc */
  236.                 false);            /* irrelevant, since no idle proc */
  237.                 
  238.     MakeReceptors ();
  239.     MakeDonors ();
  240.  
  241.     MakeFrontWind (wind);
  242. }
  243.